package com.amoby.base.commbank.commbiz;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * CommBiz系统用来处理转账业务的描述文件
 * 
 */
public class DirectEntryFile implements CommBizFile {
    protected static final Logger     logger             = LoggerFactory.getLogger(DirectEntryFile.class);
    /** BSB Number 格式 */
    public static final DecimalFormat NUM_FORMAT         = new DecimalFormat("000,000");
    /** 账户类型：收款账户 */
    public static final int           DETAIL_TYPE_CREDIT = 1;
    /** 账户类型：付款账户 */
    public static final int           DETAIL_TYPE_DEBIT  = 2;
    private String                    fileName           = null;
    private HeaderRecord              header             = null;
    private List<DetailRecord>        details            = new ArrayList<DetailRecord>();
    private TrailerRecord             trailer            = null;

    public DirectEntryFile() {
    }

    /**
     * 将PaymentFile内容存储到文件中
     * 
     * @param path 指定存储路径
     * @return 存储的文件对象
     * @throws IOException
     */
    public File store(String path) throws IOException {
        File file = new File(path, fileName);
        String content = this.serialize();
        if (file.exists()) {
            logger.warn("文件已经存在，将进行内容复写 file = " + file);
        } else {
            FileUtils.touch(file);
            logger.info("写入支付文件 file = " + file);
        }
        try (PrintWriter out = new PrintWriter(new FileOutputStream(file))) {
            out.append(content);
            out.flush();
        } catch (FileNotFoundException e) {
            throw e;
        }
        return file;
    }

    /**
     * 将信息序列化为字符串
     * 
     * @return 序列化结果
     * @throws IllegalArgumentException 信息有误
     */
    public String serialize() throws IllegalArgumentException {
        if (header == null || trailer == null || details.size() < 1) {
            throw new RuntimeException("PaymentFile内容不完整");
        }
        // 同步trailer
        syncTrailer();
        StringBuffer sb = new StringBuffer();
        sb.append(header.serialize()).append("\r\n");
        for (DetailRecord detail : details) {
            sb.append(detail.serialize()).append("\r\n");
        }
        sb.append(trailer.serialize());
        return sb.toString();
    }

    /**
     * 同步计算trailer内的金额合计
     */
    public void syncTrailer() {
        int dType = 0;
        BigDecimal creditAmount = new BigDecimal(0);
        BigDecimal debitAmount = new BigDecimal(0);
        for (DetailRecord detail : details) {
            dType = detail.getDetailType();
            switch (dType) {
            case DirectEntryFile.DETAIL_TYPE_CREDIT:
                creditAmount = creditAmount.add(new BigDecimal(detail.getAmount().toString()));
                break;
            case DirectEntryFile.DETAIL_TYPE_DEBIT:
                debitAmount = debitAmount.add(new BigDecimal(detail.getAmount().toString()));
                break;
            default:
                throw new IllegalArgumentException("detailType值不正确");
            }
        }
        trailer.setDetailCount(this.details.size());
        trailer.setNetTotalAmount(creditAmount.subtract(debitAmount).abs().doubleValue());
        trailer.setCreditTotalAmount(creditAmount.doubleValue());
        trailer.setDebitTotalAmount(debitAmount.doubleValue());
    }

    public String getFileName() {
        return this.fileName;
    }

    public HeaderRecord getHeader() {
        return this.header;
    }

    public List<DetailRecord> getDetails() {
        return this.details;
    }

    public TrailerRecord getTrailer() {
        return this.trailer;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public void setHeader(HeaderRecord header) {
        this.header = header;
    }

    public void addDetail(DetailRecord detail) {
        this.details.add(detail);
    }

    public void clearDetails() {
        this.details.clear();
    }

    public void setTrailer(TrailerRecord trailer) {
        this.trailer = trailer;
    }
}
